#ifndef __M_UTIL_H__
#define __M_UTIL_H__
#include "logerr.hpp"
#include <mysql/mysql.h>
#include <memory>
#include <jsoncpp/json/json.h>
#include <sstream>
#include <fstream>
#include <iostream>
#include <vector>
#include <iostream>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
#include <unordered_map>
#define HOST "0.0.0.0" // 监听所有网络接口
#define PORT 3306
#define USER "root"
#define PASS "BBMM1314pa"
#define DBNAME "gobang"
typedef websocketpp::server<websocketpp::config::asio> webserve_t;
class mysql_util
{
public:
    static MYSQL *mysql_create(const std::string &host, const std::string &username, const std::string &password,

                               const std::string &dbname, uint16_t port = 3306)
    {
        // 初始化mysql句柄
        MYSQL *mysql = mysql_init(NULL);

        if (mysql == NULL)
        {
            ERR_LOG("mysql init failed!");
            return nullptr;
        }
        // 建立连接
        MySQL_Create(mysql);
        return mysql;
    }
    static MYSQL* MySQL_Create(MYSQL*& mysql)
    {
        if (mysql_real_connect(mysql, HOST, USER, PASS, DBNAME, 3306, NULL, 0) == NULL)
        {

            ERR_LOG("connect mysql server failed : %s", mysql_error(mysql));
            return nullptr;
        }
        // 设置字符集
        if (mysql_set_character_set(mysql, "utf8") != 0)
        {

            ERR_LOG("set client character failed : %s", mysql_error(mysql));
            return nullptr;
        }
        return mysql;
    }
    static bool mysql_exec(MYSQL *mysql, const std::string &sql)
    {
        if(mysql_ping(mysql)!= 0)
        {
            std::cout << "MySQL链接断开了\n";
            mysql=MySQL_Create(mysql);
        }
        int ret = mysql_query(mysql, sql.c_str());
        if (ret != 0)
        {

            ERR_LOG("Executed SQL: %s", sql.c_str());

            ERR_LOG("mysql query failed : %s", mysql_error(mysql));
            return false;
        }
        return true;
    }
    static void mysql_destroy(MYSQL *mysql)
    {
        if (mysql != NULL)
        {
            mysql_close(mysql);
        }
        return;
    }
};

// class mysql_util
// {
// public:
//     static MYSQL *mysql_create(const std::string &host, const std::string &username, const std::string &password,
//                                const std::string &dbname, uint16_t port = 3306)
//     {
//         // 初始化mysql句柄
//         MYSQL *mysql = mysql_init(NULL);
//         if (mysql == NULL)
//         {
//             ERR_LOG("mysql init failed!");
//             return nullptr;
//         }
        
//         // 设置自动重连选项（重要）
//         my_bool reconnect = 1;
//         if (mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect) != 0) {
//             ERR_LOG("Failed to set auto-reconnect option: %s", mysql_error(mysql));
//         }
        
//         // 建立连接
//         if (mysql_real_connect(mysql, host.c_str(), username.c_str(), password.c_str(), dbname.c_str(), port, NULL, 0) == NULL)
//         {
//             ERR_LOG("connect mysql server failed : %s", mysql_error(mysql));
//             return nullptr;
//         }
//         // 设置字符集
//         if (mysql_set_character_set(mysql, "utf8") != 0)
//         {
//             ERR_LOG("set client character failed : %s", mysql_error(mysql));
//             return nullptr;
//         }
//         return mysql;
//     }

//     /**
//      * 检查数据库连接并自动重连
//      * @param mysql_ptr  指向 MYSQL 指针的指针（用于修改连接对象）
//      * @param host       数据库主机地址
//      * @param username   用户名
//      * @param password   密码
//      * @param dbname     数据库名
//      * @param port       端口号
//      * @return bool      true: 连接正常或重连成功, false: 连接断开且重连失败
//      */
//     static bool mysql_check_reconnect(MYSQL **mysql_ptr, 
//                                       const std::string &host = HOST, 
//                                       const std::string &username = USER,
//                                       const std::string &password = PASS,
//                                       const std::string &dbname = DBNAME,
//                                       uint16_t port = PORT)
//     {
//         // 如果连接指针为 NULL 则初始化新连接
//         if (*mysql_ptr == NULL) {
//             *mysql_ptr = mysql_create(host, username, password, dbname, port);
//             return (*mysql_ptr != NULL);
//         }
        
//         // 检查当前连接状态
//         if (mysql_ping(*mysql_ptr) == 0) {
//             return true;  // 连接正常
//         }
        
//         ERR_LOG("Connection lost: %s. Attempting reconnect...", mysql_error(*mysql_ptr));
        
//         // 关闭旧连接并重新连接
//         mysql_close(*mysql_ptr);
//         *mysql_ptr = mysql_create(host, username, password, dbname, port);
        
//         if (*mysql_ptr == NULL) {
//             ERR_LOG("Reconnect failed");
//             return false;
//         }
        
//         return true;
//     }

//     static bool mysql_exec(MYSQL *mysql, const std::string &sql)
//     {
//         // 在执行前检查连接状态（使用默认参数）
//         if (!mysql_check_reconnect(&mysql)) {
//             ERR_LOG("Cannot execute SQL without valid connection");
//             return false;
//         }
        
//         int ret = mysql_query(mysql, sql.c_str());
//         if (ret != 0)
//         {
//             ERR_LOG("Executed SQL: %s", sql.c_str());
//             ERR_LOG("mysql query failed : %s", mysql_error(mysql));
//             return false;
//         }
//         return true;
//     }

//     static void mysql_destroy(MYSQL *mysql)
//     {
//         if (mysql != NULL)
//         {
//             mysql_close(mysql);
//         }
//         return;
//     }
// };

class json_util
{
public:
    static bool serialize(const Json::Value &root, std::string &str)
    {
        Json::StreamWriterBuilder swb;
        std::unique_ptr<Json::StreamWriter> writer(swb.newStreamWriter());
        std::stringstream ss;
        int n = writer->write(root, &ss);
        if (n != 0)
        {
            ERR_LOG("serialize error");
            return false;
        }
        str = ss.str();
        return true;
    }
    static bool unserialize(const std::string &str, Json::Value &root)
    {
        Json::CharReaderBuilder crb;
        std::unique_ptr<Json::CharReader> reader(crb.newCharReader());
        std::string err;
        bool ret = reader->parse(str.c_str(), str.c_str() + str.size(), &root, &err);
        if (ret == false)
        {
            ERR_LOG("parse err");
            return false;
        }
        return true;
    }
};

class string_util
{
public:
    static int split(const std::string &src, const std::string &sep, std::vector<std::string> &res)
    {
        // 处理字符串给分割
        int sindex = 0;
        while (sindex < src.size())
        {
            // 从sindex的位置开始查找
            int pos = src.find(sep, sindex);
            if (pos == std::string::npos)
            {
                res.push_back(src.substr(sindex));
                break;
            }
            // 找到了
            // 如果是空串不加
            if (sindex == pos)
            {
                sindex += sep.size();
                continue;
            }
            res.push_back(src.substr(sindex, pos - sindex));
            sindex = pos + sep.size();
        }
        return res.size();
    }
};

class file_util
{
public:
    static bool read(const std::string &filename, std::string &body)
    {
        std::ifstream in(filename.c_str(), std::ios::binary);
        if (!in.is_open())
        {
            ERR_LOG("open %s error", filename.c_str());
            return false;
        }
        int fsize = 0;
        in.seekg(0, std::ios::end);
        fsize = in.tellg();
        in.seekg(0, std::ios::beg);
        body.resize(fsize);
        in.read(&body[0], fsize);
        if (!in.good())
        {
            ERR_LOG("read %s error", filename.c_str());
            in.close();
            return false;
        }
        in.close();
        return true;
    }
};
#endif